import React, { useEffect, useState, forwardRef, useRef } from 'react';
import { DeleteOutlined, EyeOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons';
import { Button, Modal, Upload, Progress, App } from 'antd';

import styles from './index.module.scss';

const getBase64 = (file) => {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result);
        reader.onerror = (error) => reject(error);
    });
};
const getNumber = o => {
    if (typeof o === 'number' && !isNaN(o)) return o || 1;
    if (typeof o === 'string' && !isNaN(parseInt(o)) && isFinite(o)) return Number(o) || 1;
    return 1;
}
const processFile = (file) => {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = (event) => {
            let img = new Image();
            img.src = event.target.result;

            img.onload = () => {
                resolve({
                    width: img.width,
                    height: img.height,
                    size: file.size,
                });
                img = null; // 清理资源
            };

            img.onerror = (error) => {
                reject(new Error(`无法加载图片: ${file.name}`));
            };
        };

        reader.readAsDataURL(file);
    });
};

export default forwardRef((props, ref) => {
    const { message } = App.useApp();
    const { disabled=false, shape='', limit=99, isAvatar=true, widthRange=[], heightRange=[], maxSize=0, sizeEnum=[], totalPixels=0, value, onChange, onUploadingChange } = props;
    const [previewOpen, setPreviewOpen] = useState(false);
    const [previewImage, setPreviewImage] = useState('');
    const [fileList, setFileList] = useState([]);
    const [primaryIndex, setPrimaryIndex] = useState(-1);
    const uploader = useRef(null);
    const conicColors = {
        '0%': '#ffccc7',
        '50%': '#ffe58f',
        '100%': '#00C261',
    };
    const isSingle = 1 === getNumber(limit);
    const ua = typeof navigator !== 'undefined' ? navigator.userAgent || '' : '';
    const isWeChat = /MicroMessenger/i.test(ua);
    const isIOS = /iPhone|iPad|iPod/i.test(ua);
    const isIOSWeChat = isWeChat && isIOS;

    const handleCancel = () => setPreviewOpen(false);
    const handlePreview = async (file) => {
        if (!file.url && !file.preview) {
            file.preview = await getBase64(file.originFileObj);
        }
        setPreviewImage(file.url || file.preview);
        setPreviewOpen(true);
    };
    const handleChange = (info) => {
        let newFileList = [...info.fileList];

        newFileList = newFileList.map((file) => {
            if(file.status === 'done') {
                if (OK_CODE === file?.response?.code?.toString()) {
                    let u = file.response.data;
                    file.url = u;
                }
            }

            return file;
        }).filter(Boolean);

        setFileList(newFileList);

        // 同步主图索引：如果之前主图仍存在，则保持；否则设为0（有图时）
        setPrimaryIndex(prev => {
            if (newFileList.length === 0) return -1;
            if (prev < 0 || prev >= newFileList.length) return 0;
            return prev;
        });

        // 上传中状态回传给父组件
        const isUploading = newFileList.some(i => i.status === 'uploading');
        if (typeof onUploadingChange === 'function') onUploadingChange(isUploading);

        // 没有上传中的文件，说明上传已完成，再触发表单值变更
        if(!isUploading) {
            const urls = newFileList.map(i => i.url).filter(Boolean);
            onChange({ list: urls, primaryIndex: primaryIndex < 0 && urls.length ? 0 : primaryIndex });
        }
    };
    const uploadButton = (
        <button ref={uploader} style={{border: 0, background: 'none', cursor: 'pointer',pointerEvents:'none'}}>
            <PlusOutlined />
            <div style={{marginTop: 8}}>
                上传图片
            </div>
        </button>
    );
    const getSingleButton = () => {
        const file = fileList[0];
        const status = file?.status;
        const percent = file?.percent || 0;

        return (
            'done' === status ?
                <div className={styles['single-image']}>
                    <img src={fileList[0]?.url} alt="" />
                    {
                        disabled ?
                            null
                            :
                            <div className={styles['mask']}>
                                <div className={styles['button']}><UploadOutlined/></div>
                            </div>
                    }
                </div>
                :
                'uploading' === status ?
                    <div className={styles['single-loading']}>
                        <Progress size="small" type="circle" percent={percent} strokeColor={conicColors} />
                    </div>
                    :
                    uploadButton
        );
    };

    const setPrimary = (index) => {
        setPrimaryIndex(index);
        const urls = (fileList || []).map(i => i.url).filter(Boolean);
        onChange({ list: urls, primaryIndex: index });
    };
    const itemRender = (originNode, file, currList, {download, preview, remove}) => {
        const imgUrl = file.url || file.thumbUrl || '';
        const index = (currList || []).findIndex(i => i.uid === file.uid);
        const isPrimary = index === primaryIndex;

        return (
            <div className={`${styles['upload-item']} ${'circle' === shape ? styles['circle'] : ''}`}>
                {'done' === file.status && imgUrl ? <img src={imgUrl} alt="" /> : null}
                {
                    'done' === file.status ?
                        <>
                            <div className={styles['actions']}>
                                <div className={styles['btn']}>
                                    <div className={styles['button']} onClick={e => {e.stopPropagation();preview();}}><EyeOutlined/></div>
                                    {disabled ? null : <div className={styles['button']} onClick={e => {e.stopPropagation();remove();}}><DeleteOutlined/></div>}
                                </div>
                            </div>
                            <div className={`${styles['set']} ${isPrimary ? styles['primary'] : ''}`} onClick={e => { e.stopPropagation(); setPrimary(index); }}>
                                {isPrimary ? '主图' : '设为主图'}
                            </div>
                        </>
                        :
                        null
                }
                {
                    'uploading' === file.status ?
                        <div className={styles['loading']}>
                            <Progress size="small" type="circle" percent={parseInt(file.percent)} strokeColor={conicColors} />
                        </div>
                        :
                        null
                }
            </div>
        );
    };

    const beforeUpload = async (file, fileList) => {
        if((!widthRange||!widthRange.length) && (!heightRange||!heightRange.length) && !maxSize && (!totalPixels||!totalPixels.length)) return Promise.resolve();

        return new Promise(async (resolve, reject) => {
            const {width, height, size} = await processFile(file) || {};
            if(Array.isArray(sizeEnum) && sizeEnum.length && !(sizeEnum||[]).includes(`${width}x${height}`)) {
                message.error(`参考图片大小不符合要求`);
                return Upload.LIST_IGNORE;
            }
            if(widthRange && (width < widthRange[0] || width > widthRange[1])) {
                message.error(`图片宽度：[${widthRange.toString()}]`);
                return Upload.LIST_IGNORE;
            }
            if(heightRange && (height < heightRange[0] || height > heightRange[1])) {
                message.error(`图片高度：[${heightRange.toString()}]`);
                return Upload.LIST_IGNORE;
            }
            if(maxSize && size > maxSize) {
                message.error(`图片应小于：${maxSize} Bytes`);
                return Upload.LIST_IGNORE;
            }
            if(width*height < totalPixels[0] || width*height > totalPixels[1]) {
                message.error(`图片总像素(宽*高)范围：[${totalPixels.toString()}]`);
                return Upload.LIST_IGNORE;
            }
            resolve();
        }).catch(e => Upload.LIST_IGNORE);
    };

    useEffect(() => {
        let urls = [];
        let pIndex = -1;

        if(Array.isArray(value)) {
            urls = value;
        }else if(typeof value === 'string') {
            urls = value.split(',');
        }else if(value && typeof value === 'object') {
            urls = value.list || [];
            pIndex = typeof value.primaryIndex === 'number' ? value.primaryIndex : -1;
        }

        const targetUrls = urls.filter(Boolean);
        const currUrls = (fileList || []).map(i => i.url).filter(Boolean);

        const imageList = targetUrls.map(item => {
            let o = fileList.find(i => i.url === item);
            return ({
                uid: o?.uid || item,
                name: item,
                status: 'done',
                url: item,
            })
        });

        const nextPrimaryIndex = imageList.length ? (pIndex >= 0 ? Math.min(pIndex, imageList.length - 1) : 0) : -1;
        const sameUrls = targetUrls.length === currUrls.length && targetUrls.every((u, idx) => u === currUrls[idx]);
        if (sameUrls && nextPrimaryIndex === primaryIndex) return;

        setFileList(prev => {
            const map = new Map((prev || []).map(f => [f.uid, f]));
            imageList.forEach(it => {
                if (map.has(it.uid)) {
                    const f = map.get(it.uid);
                    f.status = 'done';
                    f.url = it.url;
                } else {
                    map.set(it.uid, it);
                }
            });
            return Array.from(map.values());
        });
        setPrimaryIndex(nextPrimaryIndex);

    }, [value]);

    return (
        <>
            <Upload
                className={`${styles['upload']} ${styles[shape] || ''}`}
                action={props.action}
                listType="picture-card"
                fileList={fileList}
                showUploadList={!isAvatar}
                onPreview={handlePreview}
                onChange={handleChange}
                multiple={isAvatar ? false : !isSingle}
                accept={props.accept}
                maxCount={99} // 最多一次上传99个文件
                itemRender={itemRender}
                beforeUpload={beforeUpload}
                previewFile={isIOSWeChat ? async () => '' : undefined}
                data={props.data || {}}
                headers={{token: localStorage.getItem('accessToken')}}
                disabled={disabled}
            >
                {
                    isAvatar ?
                        getSingleButton()
                        :
                        fileList.length >= (getNumber(limit)) ? null : uploadButton
                }
            </Upload>

            <Modal
                open={previewOpen}
                title="资源预览"
                footer={null}
                onCancel={handleCancel}
                maskClosable={false}
            >
                <img
                    alt=""
                    style={{
                        width: '100%',
                        userSelect: 'none'
                    }}
                    src={previewImage}
                />
            </Modal>
        </>
    );
});